﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Xna.Framework;

namespace TD
{
    public abstract class ManagerBase<T> : GameComponent
        where T : IDisposable
    {
        /**
         * The dictionary holds all the managed objects.
         */
        private Dictionary<string, T> dictionary;

        public ManagerBase(Game game) :
            base(game)
        {
            // Do something...
        }

        /**
         * Initialize the dictionary so it can be used.
         * Also store the 'default' in it so we can always retrieve data.
         */
        public override void Initialize()
        {
            // Initialize the dictonary so it can hold our objects.
            dictionary = new Dictionary<string, T>();
            dictionary.Add("default", GetDefault());

            // Add an additional item to the list. (When not empty.
            KeyValuePair<string, T> add = AddItem();
            if (add.Key != string.Empty)
            {
                dictionary.Add(add.Key, add.Value);
            }

            base.Initialize();
        }
        protected abstract T GetDefault();
        protected virtual KeyValuePair<string, T> AddItem()
        {
            return new KeyValuePair<string, T>(string.Empty, default(T));
        }

        /**
         * Dispose of all the used resources.
         */
        protected override void Dispose(bool disposing)
        {
            foreach (KeyValuePair<string, T> value in dictionary)
            {
                T obj = value.Value;

                if (obj != null)
                {
                    obj.Dispose();
                }
            }
            dictionary = null;

            base.Dispose(disposing);
        }

        /**
         * Load content into the manager.
         */
        public void LoadAsset(string assetName)
        {
            if (!dictionary.ContainsKey(assetName))
            {
                dictionary.Add(assetName, LoadContent(assetName));
            }
            else
            {
                Debug.WriteLine("Slot for asset '" + assetName + "' is already occupied.");
            }
        }
        protected abstract T LoadContent(string assetName);

        /**
         * Use an asset from the manager.
         */
        public T UseAsset(string assetName)
        {
            if (dictionary.ContainsKey(assetName))
            {
                return dictionary[assetName];
            }
            else
            {
                Debug.WriteLine("Asset '" + assetName + "' is not precached. Using default asset.");
                return dictionary["default"];
            }
        }

        /**
         * Do an update on all the items in the manager.
         */
        public delegate void UpdateCallback(ref T obj);
        public void Update(UpdateCallback callback)
        {
            foreach (KeyValuePair<string, T> value in dictionary)
            {
                T obj = value.Value;
                if (obj != null)
                {
                    callback.Invoke(ref obj);
                }
            }
        }
    }
}
